using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VOL.Core.BaseProvider;
using VOL.Core.Extensions.AutofacManager;
using VOL.Entity.DomainModels;
using VOL.demo.IRepositories;
using Microsoft.EntityFrameworkCore;
using VOL.demo.IServices;

namespace VOL.demo.Services
{
    /// <summary>
    /// 入库单多表联查服务实现
    /// </summary>
    public class RukuService : IRukuService, IDependency
    {
        private readonly IStockInOrderModelRepository _stockInOrderRepository;
        private readonly IStockInOrderItemModelRepository _stockInOrderItemRepository;

        public RukuService(
            IStockInOrderModelRepository stockInOrderRepository,
            IStockInOrderItemModelRepository stockInOrderItemRepository)
        {
            _stockInOrderRepository = stockInOrderRepository;
            _stockInOrderItemRepository = stockInOrderItemRepository;
        }

        /// <summary>
        /// 根据ID获取入库单详情（主表+明细）
        /// </summary>
        public async Task<RukuDetailDto> GetRukuDetailByIdAsync(long id)
        {
            // 查询主表
            var mainOrder = _stockInOrderRepository.Find(x => x.Id == id && (x.IsDel == 0 || x.IsDel == null))
                .FirstOrDefault();

            if (mainOrder == null)
            {
                return null;
            }

            // 查询明细表
            var items = _stockInOrderItemRepository
                .Find(x => x.stockInOrderId == id && (x.IsDel == 0 || x.IsDel == null))
                .ToList();

            // 组装DTO
            var result = new RukuDetailDto
            {
                Id = mainOrder.Id,
                StockInCode = mainOrder.stockInCode,
                WarehouseId = mainOrder.warehouseId,
                WarehouseName = mainOrder.WarehouseName,
                StockInDate = mainOrder.stockInDate,
                RelatedOrderCode = mainOrder.relatedOrderCode,
                SupplierId = mainOrder.supplierId,
                SupplierName = mainOrder.SupplierName,
                ContactPerson = mainOrder.contactPerson,
                ContactPhone = mainOrder.contactPhone,
                UserId = mainOrder.userId,
                UserName = mainOrder.UserName,
                Status = mainOrder.status,
                StatusName = GetStatusName(mainOrder.status),
                Remark = mainOrder.remark,
                AuditUser = mainOrder.auditUser,
                AuditTime = mainOrder.auditTime,
                InOutTypeId = mainOrder.inOutTypeId,
                Creator = mainOrder.Creator,
                CreateDate = mainOrder.CreateDate,
                Modifier = mainOrder.Modifier,
                ModifyDate = mainOrder.ModifyDate,
                TotalQuantity = items.Sum(x => x.thisTimeQuantity ?? 0),
                TotalAmount = items.Sum(x => decimal.TryParse(x.upprice, out var price) ? price : 0),
                Items = items.Select(item => new RukuItemDto
                {
                    Id = item.Id,
                    StockInOrderId = item.stockInOrderId,
                    StockInCode = item.StockInCode,
                    GoodsId = item.GoodsId,
                    GoodsCode = item.GoodsCode,
                    GoodsName = item.GoodsName,
                    SpecModel = item.SpecModel,
                    UnitId = item.UnitId,
                    GoodsTypeId = item.goodsTypeId,
                    CurrentInventory = item.currentInventory,
                    PurchaseQuantity = item.purchaseQuantity,
                    InStockedQuantity = item.inStockedQuantity,
                    UnStockedQuantity = item.unStockedQuantity,
                    ThisTimeQuantity = item.thisTimeQuantity,
                    StockPosition = item.stockPosition,
                    PurchasePrice = item.purchasePrice,
                    Upprice = item.upprice,
                    BatchNo = item.batchNo,
                    ProductionDate = item.productionDate,
                    ExpireDate = item.expireDate,
                    Remark = item.remark
                }).ToList()
            };

            return result;
        }

        /// <summary>
        /// 分页查询入库单列表（主表+明细统计）
        /// </summary>
        public async Task<(List<RukuDetailDto> Data, int TotalCount)> GetRukuPagedListAsync(RukuQueryDto query)
        {
            var queryable = _stockInOrderRepository.Find(x => x.IsDel == 0 || x.IsDel == null).AsQueryable();

            // 条件筛选
            if (!string.IsNullOrEmpty(query.StockInCode))
            {
                queryable = queryable.Where(x => x.stockInCode.Contains(query.StockInCode));
            }

            if (query.WarehouseId.HasValue)
            {
                queryable = queryable.Where(x => x.warehouseId == query.WarehouseId.Value);
            }

            if (query.SupplierId.HasValue)
            {
                queryable = queryable.Where(x => x.supplierId == query.SupplierId.Value);
            }

            if (query.Status.HasValue)
            {
                queryable = queryable.Where(x => x.status == query.Status.Value);
            }

            if (query.StartDate.HasValue)
            {
                queryable = queryable.Where(x => x.stockInDate >= query.StartDate.Value);
            }

            if (query.EndDate.HasValue)
            {
                queryable = queryable.Where(x => x.stockInDate <= query.EndDate.Value);
            }

            if (!string.IsNullOrEmpty(query.Keyword))
            {
                queryable = queryable.Where(x =>
                    x.stockInCode.Contains(query.Keyword) ||
                    x.contactPerson.Contains(query.Keyword) ||
                    x.relatedOrderCode.Contains(query.Keyword));
            }

            // 获取总数
            var totalCount = queryable.Count();

            // 分页查询
            var mainOrders = queryable
                .OrderByDescending(x => x.CreateDate)
                .Skip((query.PageIndex - 1) * query.PageSize)
                .Take(query.PageSize)
                .ToList();

            // 查询所有主表对应的明细
            var orderIds = mainOrders.Select(x => x.Id).ToList();
            var allItems = _stockInOrderItemRepository
                .Find(x => orderIds.Contains(x.stockInOrderId.Value) && (x.IsDel == 0 || x.IsDel == null))
                .ToList();

            // 组装结果
            var result = mainOrders.Select(order =>
            {
                var items = allItems.Where(x => x.stockInOrderId == order.Id).ToList();

                return new RukuDetailDto
                {
                    Id = order.Id,
                    StockInCode = order.stockInCode,
                    WarehouseId = order.warehouseId,
                    WarehouseName = order.WarehouseName,
                    StockInDate = order.stockInDate,
                    RelatedOrderCode = order.relatedOrderCode,
                    SupplierId = order.supplierId,
                    SupplierName = order.SupplierName,
                    ContactPerson = order.contactPerson,
                    ContactPhone = order.contactPhone,
                    UserId = order.userId,
                    UserName = order.UserName,
                    Status = order.status,
                    StatusName = GetStatusName(order.status),
                    Remark = order.remark,
                    AuditUser = order.auditUser,
                    AuditTime = order.auditTime,
                    InOutTypeId = order.inOutTypeId,
                    Creator = order.Creator,
                    CreateDate = order.CreateDate,
                    Modifier = order.Modifier,
                    ModifyDate = order.ModifyDate,
                    TotalQuantity = items.Sum(x => x.thisTimeQuantity ?? 0),
                    TotalAmount = items.Sum(x => decimal.TryParse(x.upprice, out var price) ? price : 0),
                    Items = items.Select(item => new RukuItemDto
                    {
                        Id = item.Id,
                        StockInOrderId = item.stockInOrderId,
                        StockInCode = item.StockInCode,
                        GoodsId = item.GoodsId,
                        GoodsCode = item.GoodsCode,
                        GoodsName = item.GoodsName,
                        SpecModel = item.SpecModel,
                        UnitId = item.UnitId,
                        GoodsTypeId = item.goodsTypeId,
                        CurrentInventory = item.currentInventory,
                        PurchaseQuantity = item.purchaseQuantity,
                        InStockedQuantity = item.inStockedQuantity,
                        UnStockedQuantity = item.unStockedQuantity,
                        ThisTimeQuantity = item.thisTimeQuantity,
                        StockPosition = item.stockPosition,
                        PurchasePrice = item.purchasePrice,
                        Upprice = item.upprice,
                        BatchNo = item.batchNo,
                        ProductionDate = item.productionDate,
                        ExpireDate = item.expireDate,
                        Remark = item.remark
                    }).ToList()
                };
            }).ToList();

            return (result, totalCount);
        }

        /// <summary>
        /// 根据入库单号获取详情
        /// </summary>
        public async Task<RukuDetailDto> GetRukuDetailByCodeAsync(string stockInCode)
        {
            var mainOrder = _stockInOrderRepository
                .Find(x => x.stockInCode == stockInCode && (x.IsDel == 0 || x.IsDel == null))
                .FirstOrDefault();

            if (mainOrder == null)
            {
                return null;
            }

            return await GetRukuDetailByIdAsync(mainOrder.Id);
        }

        /// <summary>
        /// 获取入库单统计信息
        /// </summary>
        public async Task<Dictionary<string, object>> GetRukuStatisticsAsync(DateTime? startDate, DateTime? endDate)
        {
            var query = _stockInOrderRepository.Find(x => x.IsDel == 0 || x.IsDel == null).AsQueryable();

            if (startDate.HasValue)
            {
                query = query.Where(x => x.CreateDate >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                query = query.Where(x => x.CreateDate <= endDate.Value);
            }

            var orders = query.ToList();
            var orderIds = orders.Select(x => x.Id).ToList();

            var items = _stockInOrderItemRepository
                .Find(x => orderIds.Contains(x.stockInOrderId.Value) && (x.IsDel == 0 || x.IsDel == null))
                .ToList();

            var statistics = new Dictionary<string, object>
            {
                { "totalOrders", orders.Count },
                { "totalQuantity", items.Sum(x => x.thisTimeQuantity ?? 0) },
                { "totalAmount", items.Sum(x => decimal.TryParse(x.upprice, out var price) ? price : 0) },
                { "statusCounts", orders.GroupBy(x => x.status).Select(g => new { status = g.Key, count = g.Count() }).ToList() },
                { "warehouseCounts", orders.GroupBy(x => x.warehouseId).Select(g => new { warehouseId = g.Key, count = g.Count() }).ToList() }
            };

            return statistics;
        }

        /// <summary>
        /// 分页查询入库明细列表
        /// </summary>
        public async Task<(List<RukuItemDto> Data, int TotalCount)> GetRukuItemPagedListAsync(RukuItemQueryDto query)
        {
            var queryable = _stockInOrderItemRepository.Find(x => x.IsDel == 0 || x.IsDel == null).AsQueryable();

            // 条件筛选
            if (query.StockInOrderId.HasValue)
            {
                queryable = queryable.Where(x => x.stockInOrderId == query.StockInOrderId.Value);
            }

            if (!string.IsNullOrEmpty(query.StockInCode))
            {
                queryable = queryable.Where(x => x.StockInCode.Contains(query.StockInCode));
            }

            if (query.GoodsId.HasValue)
            {
                queryable = queryable.Where(x => x.GoodsId == query.GoodsId.Value);
            }

            if (!string.IsNullOrEmpty(query.GoodsCode))
            {
                queryable = queryable.Where(x => x.GoodsCode.Contains(query.GoodsCode));
            }

            if (!string.IsNullOrEmpty(query.GoodsName))
            {
                queryable = queryable.Where(x => x.GoodsName.Contains(query.GoodsName));
            }

            if (!string.IsNullOrEmpty(query.BatchNo))
            {
                queryable = queryable.Where(x => x.batchNo.Contains(query.BatchNo));
            }

            if (query.StockPosition.HasValue)
            {
                queryable = queryable.Where(x => x.stockPosition == query.StockPosition.Value);
            }

            if (query.StartDate.HasValue)
            {
                queryable = queryable.Where(x => x.CreateDate >= query.StartDate.Value);
            }

            if (query.EndDate.HasValue)
            {
                queryable = queryable.Where(x => x.CreateDate <= query.EndDate.Value);
            }

            if (!string.IsNullOrEmpty(query.Keyword))
            {
                queryable = queryable.Where(x =>
                    x.GoodsCode.Contains(query.Keyword) ||
                    x.GoodsName.Contains(query.Keyword) ||
                    x.batchNo.Contains(query.Keyword) ||
                    x.StockInCode.Contains(query.Keyword));
            }

            // 获取总数
            var totalCount = queryable.Count();

            // 分页查询
            var items = queryable
                .OrderByDescending(x => x.CreateDate)
                .Skip((query.PageIndex - 1) * query.PageSize)
                .Take(query.PageSize)
                .ToList();

            // 转换为DTO
            var result = items.Select(item => new RukuItemDto
            {
                Id = item.Id,
                StockInOrderId = item.stockInOrderId,
                StockInCode = item.StockInCode,
                GoodsId = item.GoodsId,
                GoodsCode = item.GoodsCode,
                GoodsName = item.GoodsName,
                SpecModel = item.SpecModel,
                UnitId = item.UnitId,
                GoodsTypeId = item.goodsTypeId,
                CurrentInventory = item.currentInventory,
                PurchaseQuantity = item.purchaseQuantity,
                InStockedQuantity = item.inStockedQuantity,
                UnStockedQuantity = item.unStockedQuantity,
                ThisTimeQuantity = item.thisTimeQuantity,
                StockPosition = item.stockPosition,
                PurchasePrice = item.purchasePrice,
                Upprice = item.upprice,
                BatchNo = item.batchNo,
                ProductionDate = item.productionDate,
                ExpireDate = item.expireDate,
                Remark = item.remark
            }).ToList();

            return (result, totalCount);
        }

        /// <summary>
        /// 根据入库单ID获取所有明细
        /// </summary>
        public async Task<List<RukuItemDto>> GetRukuItemsByOrderIdAsync(long stockInOrderId)
        {
            var items = _stockInOrderItemRepository
                .Find(x => x.stockInOrderId == stockInOrderId && (x.IsDel == 0 || x.IsDel == null))
                .OrderBy(x => x.Id)
                .ToList();

            var result = items.Select(item => new RukuItemDto
            {
                Id = item.Id,
                StockInOrderId = item.stockInOrderId,
                StockInCode = item.StockInCode,
                GoodsId = item.GoodsId,
                GoodsCode = item.GoodsCode,
                GoodsName = item.GoodsName,
                SpecModel = item.SpecModel,
                UnitId = item.UnitId,
                GoodsTypeId = item.goodsTypeId,
                CurrentInventory = item.currentInventory,
                PurchaseQuantity = item.purchaseQuantity,
                InStockedQuantity = item.inStockedQuantity,
                UnStockedQuantity = item.unStockedQuantity,
                ThisTimeQuantity = item.thisTimeQuantity,
                StockPosition = item.stockPosition,
                PurchasePrice = item.purchasePrice,
                Upprice = item.upprice,
                BatchNo = item.batchNo,
                ProductionDate = item.productionDate,
                ExpireDate = item.expireDate,
                Remark = item.remark
            }).ToList();

            return result;
        }

        /// <summary>
        /// 获取状态名称
        /// </summary>
        private string GetStatusName(int? status)
        {
            return status switch
            {
                0 => "草稿",
                1 => "待审核",
                2 => "已审核",
                3 => "已完成",
                4 => "已驳回",
                _ => "未知"
            };
        }
    }
}

